package com.wg.core.properties;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 统一配置访问接口
 *
 * <p>提供标准化的配置访问方式，支持基本数据类型、复杂对象及集合类型的自动转换，
 * 实现了配置数据的统一视图和强类型访问。</p>
 *
 * @author 少爷123
 */
public interface IProperties {

    /****************** 基础类型访问方法 ********************/

    /**
     * 获取字符串配置值
     *
     * @param key 配置键，使用点分命名法（如："app.name"）
     * @return 配置键对应的字符串值，不存在时返回null
     *
     * <p>示例：config.getStr("server.host") 返回 "127.0.0.1"</p>
     */
    String getStr(String key);

    /**
     * 获取字符串配置值（带默认值）
     *
     * @param key          配置键
     * @param defaultValue 当配置不存在时的默认返回值
     * @return 配置值或默认值（无null值风险）
     *
     * <p>示例：config.getStr("server.protocol", "http") 确保返回有效协议名称</p>
     */
    String getStr(String key, String defaultValue);

    /**
     * 获取整数配置值
     *
     * @param key 配置键
     * @return 配置键对应的整数值，不存在或转换失败时返回null
     *
     * <p>示例：config.getInt("server.port") 返回 8080</p>
     */
    Integer getInt(String key);

    /**
     * 获取整数配置值（带默认值）
     *
     * @param key          配置键
     * @param defaultValue 当配置不存在或转换失败时的默认值
     * @return 有效的整数配置值
     *
     * <p>示例：config.getInt("server.timeout", 5000)</p>
     */
    Integer getInt(String key, Integer defaultValue);

    /**
     * 获取长整型配置值
     *
     * @param key 配置键
     * @return 长整型值，转换失败返回null
     *
     * <p>适用于大数值场景：config.getLong("timestamp")</p>
     */
    Long getLong(String key);

    /**
     * 获取长整型配置值（带默认值）
     *
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 有效的长整型值
     */
    Long getLong(String key, Long defaultValue);

    /**
     * 获取单精度浮点数
     *
     * @param key 配置键
     * @return 单精度浮点数值，转换失败返回null
     *
     * <p><b>注意：</b>单精度浮点数值有精度损失风险，重要计算建议使用双精度</p>
     */
    Float getFloat(String key);

    /**
     * 获取单精度浮点数（带默认值）
     *
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 有效的浮点数值
     */
    Float getFloat(String key, Float defaultValue);

    /**
     * 获取双精度浮点数
     *
     * @param key 配置键
     * @return 双精度浮点数值，转换失败返回null
     *
     * <p>示例：config.getDouble("price") 返回 199.99</p>
     */
    Double getDouble(String key);

    /**
     * 获取双精度浮点数（带默认值）
     *
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 有效的双精度浮点值
     */
    Double getDouble(String key, Double defaultValue);

    /**
     * 获取短整数配置值
     *
     * @param key 配置键
     * @return 短整数值，转换失败返回null
     *
     * <p>适用于小范围整数场景：config.getShort("color.depth")</p>
     */
    Short getShort(String key);

    /**
     * 获取短整数配置值（带默认值）
     *
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 有效的短整数值
     */
    Short getShort(String key, Short defaultValue);

    /**
     * 获取字节配置值
     *
     * @param key 配置键
     * @return 字节值，转换失败返回null
     *
     * <p>适用于二进制数据场景：config.getByte("mask")</p>
     */
    Byte getByte(String key);

    /**
     * 获取字节配置值（带默认值）
     *
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 有效的字节值
     */
    Byte getByte(String key, Byte defaultValue);

    /**
     * 获取日期配置值
     *
     * @param key 配置键
     * @return 日期对象，转换失败返回null
     *
     * <p><b>日期格式支持：</b>
     * <li>ISO-8601 (yyyy-MM-dd HH:mm:ss)</li>
     * <li>时间戳（毫秒）</li></p>
     */
    Date getDate(String key);

    /**
     * 获取日期配置值（带默认值）
     *
     * @param key          配置键
     * @param defaultValue 默认日期
     * @return 有效的日期对象
     *
     * <p>示例：config.getDate("expire.time", new Date())</p>
     */
    Date getDate(String key, Date defaultValue);

    /**
     * 获取布尔配置值
     *
     * @param key 配置键
     * @return 布尔值，转换失败返回null
     *
     * <p>识别规则："true"/"1" → true, "false"/"0" → false</p>
     */
    Boolean getBool(String key);

    /**
     * 获取布尔配置值（带默认值）
     *
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 有效的布尔值
     */
    Boolean getBool(String key, Boolean defaultValue);

    /****************** 枚举类型访问方法 ********************/

    /**
     * 获取枚举配置值
     *
     * @param <E>   枚举类型
     * @param clazz 枚举类对象
     * @param key   配置键
     * @return 枚举实例，转换失败返回null
     *
     * <p>示例：LogLevel level = config.getEnum(LogLevel.class, "log.level")</p>
     */
    <E extends Enum<E>> E getEnum(Class<E> clazz, String key);

    /**
     * 获取枚举配置值（带默认值）
     *
     * @param <E>          枚举类型
     * @param clazz        枚举类对象
     * @param key          配置键
     * @param defaultValue 默认枚举值
     * @return 有效的枚举实例
     */
    <E extends Enum<E>> E getEnum(Class<E> clazz, String key, E defaultValue);

    /****************** 复杂对象绑定方法 ********************/

    /**
     * 转换为指定类型的JavaBean
     *
     * @param <T>       Bean类型
     * @param beanClass 目标类
     * @param prefix    配置键前缀
     * @return 填充后的对象实例，转换失败返回null
     *
     * <p><b>绑定规则：</b>
     * <pre>
     * 配置：db.url = jdbc:mysql://localhost
     *      db.user = root
     *
     * 调用：config.toBean(Database.class, "db")
     *
     * 结果：
     *   Database.url = "jdbc:mysql://localhost"
     *   Database.user = "root"
     * </pre></p>
     */
    <T> T toBean(Class<T> beanClass, String prefix);

    /**
     * 转换为对象列表
     *
     * @param <T>       列表元素类型
     * @param beanClass 元素类型
     * @param prefix    配置键前缀（支持下标标识）
     * @return 非空列表实例（可能包含部分转换失败的元素）
     *
     * <p><b>绑定规则：</b>
     * <pre>
     * 配置：servers[0].ip = 192.168.1.1
     *      servers[0].port = 8000
     *      servers[1].ip = 192.168.1.2
     *
     * 调用：config.toList(Server.class, "servers")
     *
     * 结果：List<Server>（包含两个Server对象）
     * </pre></p>
     */
    <T> List<T> toList(Class<T> beanClass, String prefix);

    /**
     * 转换为Map结构
     *
     * @param <T>       Map值类型
     * @param beanClass 值类型
     * @param prefix    配置键前缀
     * @return 非空Map结构（值可能为null）
     *
     * <p><b>绑定规则：</b>
     * <pre>
     * 配置：caches.user.timeout = 300
     *      caches.order.timeout = 600
     *
     * 调用：config.toMap(Integer.class, "caches")
     *
     * 结果：
     *   key="user" -> value=300
     *   key="order" -> value=600
     * </pre></p>
     */
    <T> Map<String, T> toMap(Class<T> beanClass, String prefix);

    /**
     * 获取所有配置键集合
     *
     * @return 不可修改的键集合（无null风险）
     *
     * <p>示例：Set<String> keys = config.getPropertyNames()</p>
     */
    Set<String> getPropertyNames();
}